/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2009, Around(J2)ME				                                 **
 **   All rights reserved.                                                   **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the New BSD License which accompanies this    			 **
 **   distribution.											                 **
 **   A copy is found in the textfile LICENSE.txt							 **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Main developers:                                                       **
 **     Juri Strumpflohner		http://blog.js-development.com	             **
 **		Matthias Braunhofer		http://matthias.jimdo.com                    **
 **                                                                          **
 **  **********************************************************************  */

package com.aroundj2me.xml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Vector;

import javax.microedition.lcdui.Alert;

import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import com.aroundj2me.model.Category;
import com.aroundj2me.model.Comment;
import com.aroundj2me.model.Constants;
import com.aroundj2me.model.Place;
import com.aroundj2me.utility.AlertCreator;
/**
 * Class responsible for the decoding of the XML files received from
 * the server
 *
 */
public class XMLDecoder {
	private String xmlResponseString;
	private String type;
	private KXmlParser parser;
	private Vector places;
	private Alert alert;
	
	public XMLDecoder() {
		this.parser = new KXmlParser();
		this.places = new Vector();
	}
	
	/**
	 * Does the parsing stuff
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	public void parseXML() throws XmlPullParserException, IOException{
		this.places.removeAllElements();
		
		ByteArrayInputStream s = new ByteArrayInputStream(xmlResponseString.getBytes());		

		parser.setInput(s, "ISO-8859-1");
		parser.nextTag();
		parser.require(XmlPullParser.START_TAG, null, "root");
		parser.nextTag();
		parser.require(XmlPullParser.START_TAG, null, "type");
		//read type
		type = parser.nextText();
		parser.require(XmlPullParser.END_TAG, null, "type");
		parser.nextTag();
		parser.require(XmlPullParser.START_TAG, null, "responseBody");
		
		if(type.equals(Constants.DATA_PLACE))
			parsePlaces();
		else
			parseAlert();
		
		parser.require(XmlPullParser.END_TAG, null, "responseBody");
		parser.nextTag();
		parser.require(XmlPullParser.END_TAG, null, "root");
	}

	/**
	 * Parses an alert message
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	private void parseAlert() throws XmlPullParserException, IOException {
		String alertLevel = null;
		String alertMessage = "Cause: unknown";
		while(parser.nextTag() == XmlPullParser.START_TAG){
			if(parser.getName().equals("level"))
				alertLevel = parser.nextText();
			else if(parser.getName().equals("message"))
				alertMessage = parser.nextText();
		}
		
		if(alertLevel.equals(Constants.ALERT_ERROR)){
			alert = AlertCreator.getErrorAlert(alertMessage);
		}else{
			alert = AlertCreator.getInfoAlert(alertMessage);
		}
	}

	/**
	 * parses the places out of the XML file by creating
	 * {@link Place} objects added into a Vector
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	private void parsePlaces() throws XmlPullParserException, IOException {
		//parse out places
		while(parser.nextTag() == XmlPullParser.START_TAG){
			Place p = new Place();
			parser.require(XmlPullParser.START_TAG, null, "place");

			String id = "", name = "", address = "", city="", phone="", creationDate="", user = "";
			Double distance = null;
			while(parser.nextTag() == XmlPullParser.START_TAG) {
				if(parser.getName().equals("id")){
					id = parser.nextText();
				}else if(parser.getName().equals("name")){
					name = parser.nextText();
				}else if(parser.getName().equals("address")){
					address = parser.nextText();
				}else if(parser.getName().equals("city")){
					city = parser.nextText();
				}else if(parser.getName().equals("phone")){
					phone = parser.nextText();
				}else if(parser.getName().equals("creationDate")){
					creationDate = parser.nextText();
					if(creationDate.equals("")) creationDate = null;
				}else if(parser.getName().equals("user")){
					user = parser.nextText();
				} else if(parser.getName().equals("categories")) {
					parsePlaceCategories(p);
				}else if(parser.getName().equals("comments")){
					parsePlaceComments(p);
				} else if (parser.getName().equals("distance")) {
					distance = Double.valueOf(parser.nextText());
				}
			}
			p.setId(Integer.parseInt(id));
			p.setName(name);
			p.setAddress(address);
			p.setCity(city);
			p.setPhone(phone);
			p.setCreationDate(creationDate);
			p.setUser(user);
			p.setDistance(distance);
			places.addElement(p);
			parser.require(XmlPullParser.END_TAG, null, "place");
		}
	}

	/**
	 * Parses the comments out of the XML file and adds them
	 * to the place-object passed as parameter
	 * @param place {@link Place} object to which {@link Comment} is added
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	private void parsePlaceComments(Place place) throws XmlPullParserException, IOException {
		while(parser.nextTag() == XmlPullParser.START_TAG){
			parser.require(XmlPullParser.START_TAG, null, "comment");
			String id="", content="", creationDate="", user="";
			
			while(parser.nextTag() == XmlPullParser.START_TAG){
				if(parser.getName().equals("id")){
					id = parser.nextText();
				}else if(parser.getName().equals("content")){
					content = parser.nextText();
				}else if(parser.getName().equals("creationDate")){
					creationDate = parser.nextText();
				}else if(parser.getName().equals("user")){
					user = parser.nextText();
				}
			}
			
			Comment c = new Comment();
			c.setId(Integer.parseInt(id));
			c.setContent(content);
			c.setCreationDate(creationDate);
			c.setUser(user);
			place.addComment(c);
			parser.require(XmlPullParser.END_TAG, null, "comment");
		}
	}
	
	/**
	 * Parses the categories out of the XML file and adds them
	 * to the place-object passed as parameter
	 * @param place {@link Place} object to which {@link Category} is added
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	private void parsePlaceCategories(Place place) throws XmlPullParserException, IOException {
		while(parser.nextTag() == XmlPullParser.START_TAG){
			parser.require(XmlPullParser.START_TAG, null, "category");
			String id="", name="";
			
			while(parser.nextTag() == XmlPullParser.START_TAG){
				if(parser.getName().equals("id")){
					id = parser.nextText();
				}else if(parser.getName().equals("name")){
					name = parser.nextText();
				}
			}
			
			Category c = new Category();
			c.setId(Integer.parseInt(id));
			c.setName(name);
			place.addCategory(c);
			parser.require(XmlPullParser.END_TAG, null, "category");
		}
	}

	/*
	 * Getters and Setters
	 */
	
	public String getXmlResponseString() {
		return xmlResponseString;
	}

	public void setXmlResponseString(String xmlResponseString) {
		this.xmlResponseString = xmlResponseString;
	}

	public Vector getPlaces() {
		return places;
	}

	public String getType() {
		return type;
	}

	public Alert getAlert() {
		return alert;
	}

}
